/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// gl_warp.c -- sky and water polygons

#include "quakedef.h"

/*
ID3D10VertexShader *d3d_WaterVS = NULL;
ID3D10PixelShader *d3d_WaterPS = NULL;

ID3D10VertexShader *d3d_UnderwaterVS = NULL;
ID3D10PixelShader *d3d_UnderwaterPS = NULL;

IDirect3DVertexDeclaration9 *d3d_WarpVertexDeclaration = NULL;
IDirect3DVertexDeclaration9 *d3d_WaterVertexDeclaration = NULL;

IDirect3DTexture9 *WarpRenderTarget = NULL;
IDirect3DSurface9 *WarpRenderSurface = NULL;
IDirect3DSurface9 *WarpBackBuffer = NULL;
IDirect3DTexture9 *DistortTexture = NULL;
*/

#define DISTORT_SIZE	64

QSHADER d3d_WaterSurfaces;

class CWarpHandler : public CD3DHandler
{
public:
	void OnCreateDevice (void)
	{
		d3d_WaterSurfaces.CreateShaders (IDR_WATERSHADER, "WaterVS", NULL, "WaterPS", INPUT_LAYOUT_WARP);
		/*
		D3DVERTEXELEMENT9 warplayout[] =
		{
			VDECL (0, offsetof (drawpolyvert_t, xy), D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_POSITION, 0),
			VDECL (0, offsetof (drawpolyvert_t, color), D3DDECLTYPE_D3DCOLOR, D3DDECLUSAGE_COLOR, 0),
			VDECL (0, offsetof (drawpolyvert_t, st), D3DDECLTYPE_FLOAT2, D3DDECLUSAGE_TEXCOORD, 0),
			D3DDECL_END ()
		};

		D3DVERTEXELEMENT9 waterlayout[] =
		{
			VDECL (0, offsetof (brushpolyvert_t, xyz), D3DDECLTYPE_FLOAT3, D3DDECLUSAGE_POSITION, 0),
			VDECL (0, offsetof (brushpolyvert_t, st), D3DDECLTYPE_FLOAT16_2, D3DDECLUSAGE_TEXCOORD, 0),
			VDECL (0, offsetof (brushpolyvert_t, lm), D3DDECLTYPE_FLOAT16_2, D3DDECLUSAGE_TEXCOORD, 1),
			D3DDECL_END ()
		};

		d3d_Device->CreateVertexDeclaration (warplayout, &d3d_WarpVertexDeclaration);
		d3d_Device->CreateVertexDeclaration (waterlayout, &d3d_WaterVertexDeclaration);

		d3d_WaterVS = D3D_CreateVertexShader (IDR_WATERSHADER, "WaterVS");
		d3d_WaterPS = D3D_CreatePixelShader (IDR_WATERSHADER, "WaterPS");

		d3d_UnderwaterVS = D3D_CreateVertexShader (IDR_RTTSHADER, "UnderwaterVS");
		d3d_UnderwaterPS = D3D_CreatePixelShader (IDR_RTTSHADER, "UnderwaterPS");

		// create our underwater distortion texture
		if ((DistortTexture = D3D_CreateManagedTexture (128, 128, 1, D3DFMT_X8R8G8B8)) != NULL)
		{
			D3DLOCKED_RECT lockrect;

			// and fill it in
			if (SUCCEEDED (DistortTexture->LockRect (0, &lockrect, NULL, 0)))
			{
				int x, y;
				unsigned *dst = (unsigned *) lockrect.pBits;

				for (y = 0; y < 128; y++)
				{
					for (x = 0; x < 128; x++)
					{
						((byte *) &dst[x])[0] = rand () & 255;
						((byte *) &dst[x])[1] = rand () & 255;
						((byte *) &dst[x])[2] = rand () & 255;
						((byte *) &dst[x])[3] = rand () & 255;
					}

					dst += lockrect.Pitch >> 2;
				}

				DistortTexture->UnlockRect (0);
				DistortTexture->PreLoad ();
			}
			else SAFE_RELEASE (DistortTexture);
		}
		*/
	}

	void OnReleaseDevice (void)
	{
		/*
		SAFE_RELEASE (d3d_WaterVS);
		SAFE_RELEASE (d3d_WaterPS);

		SAFE_RELEASE (d3d_UnderwaterVS);
		SAFE_RELEASE (d3d_UnderwaterPS);

		SAFE_RELEASE (DistortTexture);
		SAFE_RELEASE (d3d_WarpVertexDeclaration);
		SAFE_RELEASE (d3d_WaterVertexDeclaration);
		*/
	}

	void OnResetDevice (void)
	{
		/*
		// create a render target texture for warping at the current vid.Width and vid.Height
		d3d_Device->CreateTexture (
			vid.Width,
			vid.Height,
			1,
			D3DUSAGE_RENDERTARGET,
			D3DFMT_X8R8G8B8,
			D3DPOOL_DEFAULT,
			&WarpRenderTarget,
			NULL
		);

		// and get it's surface
		if (WarpRenderTarget)
		{
			if (FAILED (WarpRenderTarget->GetSurfaceLevel (0, &WarpRenderSurface)))
			{
				WarpRenderTarget->Release ();
				WarpRenderTarget = NULL;
			}
		}
		*/
	}

	void OnLostDevice (void)
	{
		/*
		SAFE_RELEASE (WarpRenderTarget);
		SAFE_RELEASE (WarpRenderSurface);
		SAFE_RELEASE (WarpBackBuffer);
		*/
	}
} d3d_WarpHandler;


void R_DrawWaterSurfaces (model_t *m)
{
	R_DrawGenericSurfaces (m, CHAIN_WATER, 0, &d3d_WaterSurfaces, d3d_BlendNone, d3d_ZmodeNormal);
}


void R_SetWaterAlphaState (msurface_t *surf)
{
	/*
	texture_t *t = surf->texinfo->texture;

	d3d_State->VSSetLayout (d3d_WaterVertexDeclaration);

	d3d_State->VSSetShader (d3d_WaterVS);
	d3d_State->PSSetShader (d3d_WaterPS);

	if (r_lightmap->value)
		d3d_State->PSSetTexture (0, d3d_WhiteTexture);
	else d3d_State->PSSetTexture (0, t->Texture[0]);
	*/
}


BOOL R_CheckWaterWarp (void)
{
	/*
	if (!WarpRenderTarget) return FALSE;
	if (!WarpRenderSurface) return FALSE;
	if (!DistortTexture) return FALSE;
	if (!ref.ViewLeaf[0]) return FALSE;

	if (!Mod_LeafIsUnderwater (ref.ViewLeaf[0])) return FALSE;
	if (FAILED (d3d_Device->GetRenderTarget (0, &WarpBackBuffer))) return FALSE;

	if (SUCCEEDED (d3d_Device->SetRenderTarget (0, WarpRenderSurface)))
		return TRUE;

	// can't warp or not warping at all
	SAFE_RELEASE (WarpBackBuffer);
	*/
	return FALSE;
}


void R_FinishWaterWarp (void)
{
	/*
	if (!WarpRenderTarget) return;
	if (!WarpRenderSurface) return;
	if (!WarpBackBuffer) return;

	if (FAILED (d3d_Device->SetRenderTarget (0, WarpBackBuffer)))
	{
		SAFE_RELEASE (WarpBackBuffer);
		return;
	}

	SAFE_RELEASE (WarpBackBuffer);

	// setup viewport and projection for underwater warp
	Draw_SetupProjection ();

	// send other shader constants
	d3d_State->VSSetConstantf (VS_WARPSCALE, (0.3f * (float) vid.Width) / (float) vid.Height, 0.3f);
	d3d_State->VSSetConstantf (VS_WARPSPEED, (cl.time * 0.025f) - (int) (cl.time * 0.25f));
	d3d_State->PSSetConstantf (PS_WARPFACTOR, 0.005859375f);

	d3d_State->SetRenderState (&rs_drawnoblend);
	d3d_State->VSSetLayout (d3d_WarpVertexDeclaration);

	d3d_State->PSSetSampler (0, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTADDRESS_CLAMP);
	d3d_State->PSSetSampler (1, D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTADDRESS_WRAP);
	d3d_State->PSSetSampler (2, D3DTEXF_POINT, D3DTEXF_POINT, D3DTADDRESS_CLAMP);

	d3d_State->PSSetTexture (0, WarpRenderTarget);
	d3d_State->PSSetTexture (1, DistortTexture);

	d3d_State->VSSetShader (d3d_UnderwaterVS);
	d3d_State->PSSetShader (d3d_UnderwaterPS);

	// merge the polyblend into the render to save on fillrate (conditionally don't merge)
	if (ref.ViewLeaf[0] && cls.state == ca_connected && ref.WaterTexture && gl_polyblend->value)
	{
		// send the last liquid texture
		d3d_State->PSSetTexture (2, ref.WaterTexture->Texture[0]);

		// send the contents colour percentage
		switch (ref.ViewLeaf[0]->contents)
		{
		case CONTENTS_WATER: d3d_State->PSSetConstantf (PS_SHADELIGHT, 0.5f * gl_polyblend->value, 0.35f); break;
		case CONTENTS_LAVA:	 d3d_State->PSSetConstantf (PS_SHADELIGHT, 0.6f * gl_polyblend->value, 0.50f); break;
		case CONTENTS_SLIME: d3d_State->PSSetConstantf (PS_SHADELIGHT, 0.6f * gl_polyblend->value, 0.06f); break;
		default: d3d_State->PSSetConstantf (PS_SHADELIGHT, 0.0f); break;
		}
	}
	else
	{
		// don't send a liquid colour
		d3d_State->PSSetTexture (2, d3d_BlackTexture);
		d3d_State->PSSetConstantf (PS_SHADELIGHT, 0.0f);
	}

	// send the actual blend colours
	// drawing the full texture to the scaled-down viewport, reusing the draw funcs
	// because we can and so that we don't need to build new buffers here
	if (cls.state != ca_connected || !gl_polyblend->value || !v_blend[3])
		Draw_FullscreenQuad (0);
	else Draw_FullscreenQuad (*((int *) v_blend));

	// disable polyblend to save on fillrate
	v_blend[3] = 0;
	*/
}


QTEXTURE *D3D_CaptureScreen (void)
{
	/*
	// if we failed to create the render targets then don't do it
	if (!WarpRenderTarget) return NULL;
	if (!WarpRenderSurface) return NULL;

	// if we're in an RTT pass we can't capture it
	if (WarpBackBuffer) return NULL;

	if (SUCCEEDED (d3d_Device->GetRenderTarget (0, &WarpBackBuffer)))
	{
		d3d_Device->StretchRect (
			WarpBackBuffer,
			NULL,
			WarpRenderSurface,
			NULL,
			D3DTEXF_NONE
		);

		SAFE_RELEASE (WarpBackBuffer);

		return WarpRenderTarget;
	}
	*/

	// failed
	return NULL;
}


